import 'dart:typed_data';

import 'package:bluetooth_protocols_plugin/src/base/statistics/statistics_once_data_base.dart';
import 'package:bluetooth_protocols_plugin/src/tools/utils.dart';
import 'lorin_record_date.dart';

/*
  若读请求携带的参数为空，则应答如下：
  uint8_t 记录总数 0~64
  uint32_t index 最近一条记录的编号

  若读请求携带的参数为 uint8_t 起始编号 + uint8_t 数目n，则应答如下：
  uint8_t 起始序号 + uint8_t 数目n + uint8_t 总数 + uint8_t 每条记录长度+VX_RECORD[n]
  typedef struct{        //38 bytes
      uint32_t index;                //记录编号
      RECORD_DATE date;              //记录生成日期
      uint16_t max_speed;            //最高速度         单位 0.01km/h
      uint16_t max_power;            //最大总功率       单位 W
      uint16_t max_motor_power;      //最大电机输出功率 单位 W
      int8_t max_mos_temp;           //MOS最高温度      单位 °C  偏置80，即数值0代表80°C
      int8_t max_motor_temp;         //电机最高温度     单位 °C  偏置80，即数值0代表80°C
      int8_t max_battery_temp;       //电池最高温度     单位 °C  偏置80，即数值0代表80°C
      int8_t max_board_temp;         //主板高温区最高温度  单位 °C  偏置80，即数值0代表80°C
      uint32_t mileage;              //里程             单位 0.01km
      uint32_t consumption;          //消耗能量         单位 0.01kJ
      uint32_t recovery;             //回收能量         单位 0.01kJ
      uint32_t ride_time;            //骑行时间         单位 S
      uint32_t power_on_time;        //开机时间         单位 S
  }VX_RECORD;

  其中 RECORD_DATE 定义如下
  typedef struct{
      uint32_t year   : 6; // 2020-2084
      uint32_t month  : 4; // 1-12
      uint32_t day    : 5; // 1-31
      uint32_t hour   : 5; // 0-23
      uint32_t minute : 6; // 0-59
      uint32_t second : 6; // 0-59
  }RECORD_DATE;
*/

// 统计总数据基类
abstract class LorinStatisticsOnceData extends StatisticsOnceDataBase {
  // 是否为空参数
  bool isEmptyPara = true;

  int count = 0; // 记录总数 0~64
  int index = 0; // 记录编号
  RecordDate date = RecordDate.fromBytes(Uint8List(4)); // 记录生成日期
  int maxSpeed = 0; // 最高速度，单位 0.01km/h
  int maxPower = 0; // 最大总功率，单位 W
  int maxMotorPower = 0; // 最大电机输出功率，单位 W
  int maxMosTemp = 0; // MOS最高温度，单位 °C，偏置80，即数值0代表80°C
  int maxMotorTemp = 0; // 电机最高温度，单位 °C，偏置80，即数值0代表80°C
  int maxBatteryTemp = 0; // 电池最高温度，单位 °C，偏置80，即数值0代表80°C
  int maxBoardTemp = 0; // 主板高温区最高温度，单位 °C，偏置80，即数值0代表80°C
  int mileage = 0; // 里程，单位 0.01km
  int consumption = 0; // 消耗能量，单位 0.01kJ
  int recovery = 0; // 回收能量，单位 0.01kJ
  int rideTime = 0; // 骑行时间，单位 S
  int powerOnTime = 0; // 开机时间，单位 S

  // 从字节数据解析
  LorinStatisticsOnceData.fromBytes(Uint8List bytes) : super.fromBytes(bytes) {
    if (bytes.length == emptyParaRspLength) {
      isEmptyPara = true;
      count = bytes[0];
      index = ByteData.sublistView(bytes).getUint32(1, Endian.little);
    } else {
      if (bytes.length < minLength) {
        throw ArgumentError(
            '字节数组长度不足，无法解析 $runtimeType，期望长度至少为 $minLength，实际长度为 ${bytes.length}');
      }
      isEmptyPara = false;
      // 起始序号 + 数目 + 总数 + 每条记录长度 + VX_RECORD[n]
      int offset = 4;
      var byteData = ByteData.sublistView(bytes);
      index = byteData.getUint32(offset, Endian.little);
      date = RecordDate.fromBytes(bytes.sublist(offset + 4, offset + 8));
      maxSpeed = byteData.getUint16(offset + 8, Endian.little);
      maxPower = byteData.getUint16(offset + 10, Endian.little);
      maxMotorPower = byteData.getUint16(offset + 12, Endian.little);
      maxMosTemp = byteData.getInt8(offset + 14) + 80;
      maxMotorTemp = byteData.getInt8(offset + 15) + 80;
      maxBatteryTemp = byteData.getInt8(offset + 16) + 80;
      maxBoardTemp = byteData.getInt8(offset + 17) + 80;
      mileage = byteData.getUint32(offset + 18, Endian.little);
      consumption = byteData.getUint32(offset + 22, Endian.little);
      recovery = byteData.getUint32(offset + 26, Endian.little);
      rideTime = byteData.getUint32(offset + 30, Endian.little);
      powerOnTime = byteData.getUint32(offset + 34, Endian.little);
    }
  }

  @override
  int dataIntValue() {
    return Utils.computeDataIntVal(toBytes());
  }

  @override
  int dataLength() {
    return toBytes().length;
  }

  @override
  int get minLength => 38;

  // 当请求携带参数为空时
  int get emptyParaRspLength => 5;

  @override
  Uint8List toBytes() {
    var byteData = ByteData(minLength);
    if (isEmptyPara) {
      byteData.setUint8(0, count);
      byteData.setUint32(1, index, Endian.little);
      return byteData.buffer.asUint8List();
    }
    byteData.setUint32(0, index, Endian.little);
    byteData.buffer.asUint8List(4, 4).setAll(0, date.toBytes());
    byteData.setUint16(8, maxSpeed, Endian.little);
    byteData.setUint16(10, maxPower, Endian.little);
    byteData.setUint16(12, maxMotorPower, Endian.little);
    byteData.setInt8(14, maxMosTemp - 80);
    byteData.setInt8(15, maxMotorTemp - 80);
    byteData.setInt8(16, maxBatteryTemp - 80);
    byteData.setInt8(17, maxBoardTemp - 80);
    byteData.setUint32(18, mileage, Endian.little);
    byteData.setUint32(22, consumption, Endian.little);
    byteData.setUint32(26, recovery, Endian.little);
    byteData.setUint32(30, rideTime, Endian.little);
    byteData.setUint32(34, powerOnTime, Endian.little);
    return byteData.buffer.asUint8List();
  }

  @override
  Map<String, dynamic> toMap() {
    if (isEmptyPara) {
      return {
        'count': count,
        'index': index,
      };
    }
    return {
      'index': index,
      'date': date.toMap(),
      'maxSpeed': maxSpeed,
      'maxPower': maxPower,
      'maxMotorPower': maxMotorPower,
      'maxMosTemp': maxMosTemp,
      'maxMotorTemp': maxMotorTemp,
      'maxBatteryTemp': maxBatteryTemp,
      'maxBoardTemp': maxBoardTemp,
      'single_mileage': mileage,
      'single_consumption': consumption,
      'single_recovery': recovery,
      'single_ride_time': rideTime,
      'single_power_on_time': powerOnTime,
    };
  }
}
